/**
 * Marker模块 - 负责地图标记点的创建、管理和交互
 * 提供标记点批量创建、事件绑定和实例管理功能
 */
import InfoWindow from "../InfoWindow/index";
import { coordinateConverter } from "../../utils/coordinateConverter";
import type { MarkerModule, MarkerInstance, MarkerOptions, ExtraOptions } from "./types/index";

class MarkerModules {
  public name = "Marker";
  public AMap: any = null;
  public map: any = null;
  // 存储所有创建的标记点实例，便于统一管理
  private markerInstances: MarkerInstance[] = [];
  private infoWindow: any = null;
  private extra: ExtraOptions = {};

  /**
   * 初始化方法 - 批量创建并添加标记点到地图
   * @param options - 标记点配置数组
   * @param extra - 额外配置
   * @returns Promise<MarkerModule> - 返回创建的标记点模块
   * @throws {TypeError} 当参数不是数组时抛出警告
   */
  public init(options: MarkerOptions[], extra: ExtraOptions = {}): Promise<MarkerModule> {
    return new Promise((resolve, reject) => {
      if (!Array.isArray(options)) {
        console.warn("Marker模块: 参数必须是标记点配置数组");
        reject(new TypeError("参数必须是数组"));
        return;
      }
      this.extra = extra;
      // 先移除已有标记点
      this.removeMarkers();

      // 过滤无效配置并创建标记点
      this.markerInstances = options
        .filter(option => option && typeof option === "object")
        .map(option => this.createSingleMarker(option))
        .filter((instance): instance is MarkerInstance => Boolean(instance));

      this.map.setFitView();
      // 返回创建的标记点实例数组
      resolve({
        name: "Marker",
        instance: this.markerInstances,
        events: {
          remove: this.removeMarkers.bind(this)
        }
      });
    });
  }

  /**
   * 创建并设置单个标记点
   * @param option - 标记点配置选项
   * @returns {MarkerInstance | null} 创建的标记点实例或null
   */
  public createSingleMarker(option: MarkerOptions): MarkerInstance | null {
    if (!option || !option.position) {
      console.warn("无效的标记点配置");
      return null;
    }

    try {
      let position: [number, number] = option.position;
      if (this.extra?.coordTransform && coordinateConverter[this.extra?.coordTransform]) {
        const t = coordinateConverter[this.extra?.coordTransform]({
          lng: option.position[0],
          lat: option.position[1]
        });
        position = [t.lng, t.lat];
      }

      const marker = new this.AMap.Marker({
        ...option,
        // 确保map属性不会被覆盖
        map: this.map,
        position
      });

      marker.setMap(this.map);
      // 标记点默认绑定infoWindow信息窗
      !option.extData?.relieveInfoWindow && this.bindMarkerEvents(marker);
      return marker;
    } catch (error) {
      console.error("创建标记点失败:", error);
      return null;
    }
  }

  /**
   * 移除所有标记点
   */
  public removeMarkers() {
    this.map.remove(this.markerInstances);
    this.markerInstances = [];
    if (this.infoWindow) {
      this.infoWindow.close();
    }
  }

  /**
   * 绑定标记点交互事件
   * @param marker - AMap标记点实例
   */
  public bindMarkerEvents(marker: any): void {
    InfoWindow.AMap = this.AMap;
    InfoWindow.map = this.map;
    const extData = marker.getExtData();
    marker.on("click", () => {
      this.infoWindow = InfoWindow.createSingleInfoWindow(
        {
          position: marker.getPosition(),
          content: extData?.infoWindowOpts?.content,
          ...extData?.infoWindowOpts
        },
        this.map
      );
    });
  }
}

export default new MarkerModules();
